package cn.smile.utils;

import cn.smile.bean.dto.core.UploadFileDTO;
import cn.smile.commons.constant.CommonConstant;
import cn.smile.commons.constant.NumberConstant;
import cn.smile.commons.exceptions.BusinessException;
import cn.smile.commons.response.MyResponseCode;
import cn.smile.config.MinIoConfig;
import io.minio.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

import jakarta.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * 文件上传 Minio 工具类
 *
 * @author smile-jt
 */
@Slf4j
@Component
public class FileUploadUtil {

    @Resource
    private MinioClient minioClient;
    @Resource
    private MinIoConfig config;


    /**
     * 上传文件到对象服务器
     *
     * @param file     文件对象
     * @param isRename 是否重命名 true-重命名, false-不重命名
     * @return 上传文件结果对象
     */
    public UploadFileDTO uploadFile(MultipartFile file, Boolean isRename) {
        UploadFileDTO dto = new UploadFileDTO();
        String oldFileName = file.getOriginalFilename();
        if (ObjectUtils.isEmpty(oldFileName)) {
            throw new BusinessException(MyResponseCode.FILE_NAME_ERROR);
        }
        dto.setOldFileName(oldFileName);
        try {
            if (!this.bucketExists(config.getBucketName())) {
                this.makeBucket(config.getBucketName());
            }
            if (isRename) {
                String fileSuffix = oldFileName.substring(oldFileName.lastIndexOf("."));
                oldFileName = String.format(CommonConstant.FILE_NAME_FORMAT, UUID.randomUUID(), fileSuffix);
            }
            String newFileName = String.format("%s/%s", DateFormatUtil.parseDateToStr(new Date(), DateFormatUtil.DATE_TIME_FORMAT_2), oldFileName);
            PutObjectArgs args = PutObjectArgs.builder().bucket(config.getBucketName()).object(newFileName).stream(file.getInputStream(), file.getSize(), NumberConstant.MINUS_ONE).contentType(file.getContentType()).build();
            minioClient.putObject(args);
            dto.setNewFileName(newFileName);
            dto.setBucketName(config.getBucketName());
            dto.setUploadResult(Boolean.TRUE);
            dto.setDownloadUrl(String.format(CommonConstant.REQUEST_URL_FORMAT, config.getVisitPrefix(), config.getBucketName(), newFileName));
        } catch (Exception e) {
            log.error("文件上传错误, e:", e);
            dto.setUploadResult(Boolean.FALSE);
        }
        return dto;
    }

    /**
     * 删除文件
     *
     * @param fileNameList 文件集合
     */
    public void delFile(List<String> fileNameList) {
        if (!CollectionUtils.isEmpty(fileNameList)) {
            for (String fileName : fileNameList) {
                try {
                    minioClient.removeObject(RemoveObjectArgs.builder().bucket(config.getBucketName()).object(fileName).build());
                } catch (Exception e) {
                    log.error("删除 MinIO 文件异常, e : ", e);
                }
            }
        }
    }

    /**
     * 检查文件桶是否存在
     *
     * @param bucketName 文件桶名称
     * @return 检查结果
     */
    public boolean bucketExists(String bucketName) {
        boolean exists;
        try {
            exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
        } catch (Exception e) {
            log.error("MinIO 文件桶检查异常, e", e);
            throw new BusinessException(MyResponseCode.ERROR_MIN_IO_BUCKET);
        }
        return exists;
    }

    /**
     * 创建 MinIO 文件桶
     *
     * @param bucketName 文件桶名称
     */
    public void makeBucket(String bucketName) {
        try {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
        } catch (Exception e) {
            log.error("MinIO 文件桶创建异常, e", e);
            throw new BusinessException(MyResponseCode.ERROR_MIN_IO_BUCKET);
        }
    }
}
